package com.dzl.util.wx.third;

import com.alibaba.fastjson.JSONObject;
import com.dzl.config.exception.CommonException;
import com.dzl.util.EmptyUtils;
import com.dzl.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 功能描述：微信服务商工具类
 * @Author: liuguanjun
 * @Date: 2022/01/15 17:27
 */
@Slf4j
public class WxThirdUtil {



    /**
     * 获取票据，若缓存中存在，则从缓存中取值，否则，走直接发送请求的获取流程
     * 说明：令牌（component_access_token）是第三方平台接口的调用凭据。令牌的获取是有限制的，每个令牌的有效期为 2 小时(7200 s)，请自行做好令牌的管理，在令牌快过期时（比如1小时50分），重新调用接口获取。
     */
    public static String getOpenAccToken(){
        String token = WebChatCatchUtil.getWeixinOpenComponentAccesstoken();
        if (EmptyUtils.isEmpty(token)) {
            token = getOpenAccTokenInstant();
        }
        return token;
    }

    /**
     * 获取预授权码，判断缓存中是否存在，若不存在，则走直接获取流程
     * @return
     */
    public static String getPreAuthCode() {
        String authCode = WebChatCatchUtil.getWeixinOpenPreAuthCode();
        if (EmptyUtils.isEmpty(authCode)) {
            authCode = getPreAuthCodeInstant();
        }
        return authCode;
    }

    /**
     * 获取/刷新接口调用令牌
     * 在公众号/小程序接口调用令牌（authorizer_access_token）失效时，可以使用刷新令牌（authorizer_refresh_token）获取新的接口调用令牌
     * @param authorizerAppid 授权方 appid
     * @param authorizerRefreshToken 刷新令牌，获取授权信息时得到
     */
    public static String getAuthorizerAccessToken(String authorizerAppid,String authorizerRefreshToken){
        String authorizerAccessToken = WebChatCatchUtil.getWeixinOpenAuthorizerAccessToken(authorizerAppid);
        if (EmptyUtils.isEmpty(authorizerAccessToken)) {
            authorizerAccessToken = getAuthorizerAccessTokenInstant(authorizerAppid,authorizerRefreshToken);
        }
        return authorizerAccessToken;
    }





    /**
     * 令牌
     * 令牌（component_access_token）是第三方平台接口的调用凭据。令牌的获取是有限制的，每个令牌的有效期为 2 小时，请自行做好令牌的管理，在令牌快过期时（比如1小时50分），重新调用接口获取。
     * 如未特殊说明，令牌一般作为被调用接口的 GET 参数 component_access_token 的值使用
     * @return
     */
    private static String getOpenAccTokenInstant(){
        String componentVerifyTicket = WebChatCatchUtil.getWeixinOpenComponentVerifyTicket();  //获取验证票据
        //设置请求参数
        JSONObject json = new JSONObject();
        json.put("component_appid", ComponentConfig.sComponentAppId);
        json.put("component_appsecret", ComponentConfig.sComponentAppSecret);
        json.put("component_verify_ticket", componentVerifyTicket);
        //使用POST请求，获取请求结果
        String API_COMPONENT_TOKEN_URl = WeixinImSetting.OPEN_URL_COMPONENTTOKEN;
        String responseData = HttpUtil.sendPostUrl(API_COMPONENT_TOKEN_URl, json.toString(),"utf-8");//此处为封装的工具类，发送的是HTTPS请求
        log.info("====================WxThirdUtil getOpenAccTokenInstant param：component_appid:" + ComponentConfig.sComponentAppId+",component_appsecret"+ComponentConfig.sComponentAppSecret+",component_verify_ticket"+componentVerifyTicket);
        JSONObject postData = JSONObject.parseObject(responseData);
        log.info("====================WxThirdUtil getOpenAccTokenInstant 返回post结果：" + postData);
        String token = (String) postData.get("component_access_token");  //第三方平台 access_token
        Integer expires_in = (Integer) postData.get("expires_in");     //有效期，单位：秒
        WebChatCatchUtil.setWeixinOpenComponentAccessToken(token,expires_in); //写入缓存
        return token;

    }

    /**
     * 获取预授权码，判断缓存中是否存在，若不存在，则走直接获取流程
     */
    private static String getPreAuthCodeInstant(){
        String accessToken = getOpenAccToken();
        //设置请求参数
        JSONObject json = new JSONObject();
        json.put("component_appid", ComponentConfig.sComponentAppId);
        String API_COMPONENT_TOKEN_URl = WeixinImSetting.OPEN_URL_PREAUTHCODE;
        API_COMPONENT_TOKEN_URl = API_COMPONENT_TOKEN_URl.replace("COMPONENT_ACCESS_TOKEN",accessToken);
        String responseData = HttpUtil.sendPostUrl(API_COMPONENT_TOKEN_URl , json.toString(), "utf-8"); //发送HTTPS请求
        log.info("====================WxThirdUtil getPreAuthCodeInstant param：component_appid:" + ComponentConfig.sComponentAppId+",API_COMPONENT_TOKEN_URl"+API_COMPONENT_TOKEN_URl);
        JSONObject postData = JSONObject.parseObject(responseData);
        log.info("====================WxThirdUtil getPreAuthCodeInstant 返回post结果：" + postData);
        String authCode = (String) postData.get("pre_auth_code");
        Integer expires_in = (Integer) postData.get("expires_in");     //有效期，单位：秒
        WebChatCatchUtil.setWeixinOpenPreAuthCode(authCode,expires_in); //存入缓存
        return authCode;
    }

    /**
     * 获取/刷新接口调用令牌
     * 在公众号/小程序接口调用令牌（authorizer_access_token）失效时，可以使用刷新令牌（authorizer_refresh_token）获取新的接口调用令牌
     * @param authorizerAppid 授权方 appid
     * @param authorizerRefreshToken 刷新令牌，获取授权信息时得到
     */
    private static String getAuthorizerAccessTokenInstant(String authorizerAppid,String authorizerRefreshToken){
        String componentAccessToken = getOpenAccToken();   //令牌
        //设置请求参数
        JSONObject json = new JSONObject();
        json.put("component_appid", ComponentConfig.sComponentAppId);
        json.put("authorizer_appid", authorizerAppid);
        json.put("authorizer_refresh_token", authorizerRefreshToken);
        String API_COMPONENT_TOKEN_URl = WeixinImSetting.OPEN_URL_AUTHORIZERTOKEN;
        API_COMPONENT_TOKEN_URl = API_COMPONENT_TOKEN_URl.replace("COMPONENT_ACCESS_TOKEN",componentAccessToken);
        String responseData = HttpUtil.sendPostUrl(API_COMPONENT_TOKEN_URl, json.toString(), "utf-8");
        log.info("====================WxThirdUtil getAuthorizerAccessTokenInstant param：component_appid:" + ComponentConfig.sComponentAppId+",authorizer_appid"+authorizerAppid+",authorizer_refresh_token"+authorizerRefreshToken+",API_COMPONENT_TOKEN_URl"+API_COMPONENT_TOKEN_URl);
        JSONObject postData = JSONObject.parseObject(responseData);
        log.info("====================WxThirdUtil getAuthorizerAccessTokenInstant 返回post结果：" + postData);
        if("0".equals(postData.getString("errcode")) && "ok".equalsIgnoreCase(postData.getString("errmsg"))){
            String authorizerAccessToken = (String) postData.get("authorizer_access_token");
            Integer expires_in = (Integer) postData.get("expires_in");     //有效期，单位：秒
            WebChatCatchUtil.setWeixinOpenAuthorizerAccessToken(authorizerAppid,authorizerAccessToken,expires_in);
            return authorizerAccessToken;
        } else {
            throw new CommonException("WxThirdUtil getAuthorizerAccessTokenInstant fail -->"+postData.getInteger("errcode")+postData.getString("errmsg"));
        }

    }

}
